package com.xx.bysj.service.imp;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xx.bysj.BysjApplication;
import com.xx.bysj.dto.HnOrder;
import com.xx.bysj.dto.HnOrderInfo;
import com.xx.bysj.dto.HnOrderPhoto;
import com.xx.bysj.dto.HnUser;
import com.xx.bysj.dto.UploadOrderImgDto;
import com.xx.bysj.mapper.HnOrderInfoMapper;
import com.xx.bysj.mapper.HnOrderMapper;
import com.xx.bysj.mapper.HnOrderPhotoMapper;
import com.xx.bysj.mapper.HnUserMapper;
import com.xx.bysj.service.OrderService;
import com.xx.bysj.utils.RedisIdWorker;
import com.xx.bysj.utils.Result;
import org.apache.commons.collections4.CollectionUtils;
import org.bson.types.Binary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.xx.bysj.utils.RedisConstants.ORDER_ADD_CODE_KEY;

@Service
@Transactional(rollbackFor = Exception.class)
public class OrderServiceImpl implements OrderService {

    @Autowired
    private HnOrderInfoMapper orderInfoMapper;

    @Autowired
    private HnOrderMapper orderMapper;

    @Resource
    private RedisIdWorker redisIdWorker;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private HnOrderPhotoMapper orderPhotoMapper;

    @Autowired
    private HnUserMapper userMapper;

    private static final String NEW = "new";
    private static final String UPDATE = "update";

    private static final Logger logger = LoggerFactory.getLogger(BysjApplication.class);


    @Override
    public Result addOrder(HnOrderInfo orderInfo, Authentication authentication, HttpServletRequest request,List<String> imgList) {
        String message = "";
        try {
            long num = redisIdWorker.nextId(ORDER_ADD_CODE_KEY);
            HnOrder order = new HnOrder();
            order.setOrderNum(String.valueOf(num));
            order.setOrderUserId(orderInfo.getUserId());
            order.setOrderStatus(NEW);
            order.setOrderStartTime(new Date());
            order.setVersionNumber(0);
            orderMapper.insert(order);

            orderInfo.setOrderId(order.getOrderId());
            orderInfo.setVersionNumber(0);
            orderInfoMapper.insert(orderInfo);

            if (CollectionUtils.isNotEmpty(imgList)) {
                for (int i = 0; i <imgList.size() ; i++) {
                    HnOrderPhoto photo = new HnOrderPhoto();
                    photo.setOrderInfoId(orderInfo.getOrderInfoId());
                    photo.setOrderPhotoUrl(imgList.get(i));
                    orderPhotoMapper.insert(photo);
                }
            }
            message = "提交成功,订单号为:"+order.getOrderNum();
        } catch (Exception e) {
            logger.error("Request URL : {}, Exception : {}",request.getRequestURL(),e);
            throw new RuntimeException("提交失败");
        }
        return Result.success(message);
    }

    @Override
    public Result uploadMongoDb(MultipartFile[] files, HttpServletRequest request, Authentication authentication) {
        if (files.length == 0){
            return Result.fail("文件为空，请选择文件");
        }
        try {
            List<String> urls = new ArrayList<>();
            for(MultipartFile file : files){
                // 赋值上传图片的属性
                String fileName = file.getOriginalFilename();
                UploadOrderImgDto uploadImg = new UploadOrderImgDto()
                        .setName(fileName)
                        .setCreatedTime(LocalDateTime.now())
                        .setContent(new Binary(file.getBytes()))
                        .setContentType(file.getContentType())
                        .setSize(file.getSize());

                // 通过 mongoTemplate 保存后，会把数据库自动生成的主键赋值到这个对象上
                UploadOrderImgDto savedFile = mongoTemplate.save(uploadImg);
                // 构造好这个图片的请求地址返回给前端，我们后面实现这个请求
                String url = "/order/mongoDbShow/" + savedFile.getId();
                urls.add(url);
            }
            return Result.success("上传成功",urls);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public void mongoDbShow(String id, HttpServletResponse response) {
        byte[] data = null;
        UploadOrderImgDto file = mongoTemplate.findById(id, UploadOrderImgDto.class);
        if (file != null) {
            data = file.getContent().getData();
        }
        if (null != data) {
            try (ServletOutputStream ot = response.getOutputStream()) {
                ot.write(data, 0, data.length);
                ot.flush();
            } catch (Exception e) {
                throw new NullPointerException("无法获取图片信息!");
            }
        }
        response.setContentType("image/jpeg, image/jpg, image/png, image/gif");
    }

    @Override
    public Result query(HnOrder order, Authentication authentication, int page, int limit) {
        HnUser dto = new HnUser();
        dto.setUserName(authentication.getName());
        HnUser user = userMapper.selectByUserName(dto);
        if (user.getUserRoleId() != 0) {
            order.setOrderUserId(user.getUserId());
        }
        PageHelper.startPage(page,limit);
        List<HnOrder> orderList = orderMapper.selectByOrder(order);
        PageInfo<HnOrder> pageInfo = new PageInfo<>(orderList);
        return Result.querySuccess(orderList,(int)pageInfo.getTotal());
    }

    @Override
    public Result cancel(String orderNum, Authentication authentication) {
        HnOrder order = new HnOrder();
        order.setOrderNum(orderNum);
        order.setOrderStatus("cancel");
        orderMapper.updateCancel(order);
        return Result.success("取消成功");
    }

    @Override
    public Result edit(HnOrderInfo order, Authentication authentication, List<String> imgList) {
        HnOrder orderUpdate = new HnOrder();
        orderUpdate.setOrderNum(order.getOrderNum());
        orderUpdate.setOrderUserId(order.getUserId());
        orderUpdate.setOrderStatus(UPDATE);
        try {
            orderMapper.update(orderUpdate);
            orderInfoMapper.update(order);
            if (CollectionUtils.isNotEmpty(imgList)) {
                orderPhotoMapper.deleteByOrderInfoId(order.getOrderInfoId());
                for (int i = 0; i <imgList.size() ; i++) {
                    HnOrderPhoto photo = new HnOrderPhoto();
                    photo.setOrderInfoId(order.getOrderInfoId());
                    photo.setOrderPhotoUrl(imgList.get(i));
                    orderPhotoMapper.insert(photo);
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new RuntimeException("更新失败");
        }
        return Result.success("更新成功");
    }

    @Override
    public Result queryReceive(HnOrder order, Authentication authentication, int page, int limit) {
        HnUser dto = new HnUser();
        dto.setUserName(authentication.getName());
        HnUser user = userMapper.selectByUserName(dto);
        if (user.getUserRoleId() != 0) {
            order.setOrderReceiveUserId(user.getUserId());
        }
        PageHelper.startPage(page,limit);
        List<HnOrder> orderList = orderMapper.queryReceive(order);
        PageInfo<HnOrder> pageInfo = new PageInfo<>(orderList);
        return Result.querySuccess(orderList,(int)pageInfo.getTotal());
    }

    @Override
    public Result finish(String orderNum, Authentication authentication) {
        HnOrder order = new HnOrder();
        order.setOrderNum(orderNum);
        order.setOrderStatus("complete");
        order.setOrderEndTime(new Date());
        orderMapper.updateFinish(order);
        return Result.success("已完成订单");
    }
}
